<?php
/*
  功能：平台权限 model
  作者：gsl
  时间：2018-09-21
*/

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class AdminPermission extends BaseModel {
    use SoftDeletes;
    protected $dates = ['deleted_at'];
    protected $table='admin_permission';  //绑定表
    protected $appends = ['child_num'];
    /**
     * @var array
     */
    public static $httpMethods = [
        'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD',
    ];

    /**
     * @var array
     */
    protected $fillable = ['http_method'];

    /**
     * 下级数量
     */
    public function getChildNumAttribute(){
        if (!isset($this->attributes['id']) || empty($this->attributes['id'])) {
            return 0;
        }
        $pid = $this->attributes['id'];
        $child_num = self::getChildNum($pid);
        return $child_num ? $child_num : 0;
    }

    /**
     * 获取子集数量
     * @param $pid 父ID
     * @return mixed
     */
    public static function getChildNum($pid){
        return self::where('pid',$pid)->count();
    }

    /**
     * 获取面包屑
     * @param $route 菜单路由
     * @return array
     */
    public static function getCrumbs($route)
    {
        $menuId = self::where('url', $route)->value('id');
        if ($menuId) {
            return $data[] = self::recursionGetCrumbs($menuId);
        }
        return [];
    }

    /**
     * 递归面包屑
     * @param $menuId 菜单ID
     * @return array
     */
    public static function recursionGetCrumbs($menuId)
    {
        $data = [];
        $list = self::where('id', $menuId)->first(['id', 'pid', 'name', 'url']);
        if ($list) {
            $list = $list->toArray();
            if ($list['pid'] > 0) {
                $data = self::recursionGetCrumbs($list['pid']);
            }
            $data[] = ['id' => $list['id'], 'menu_route' => $list['url'], 'title' => $list['name']];
        }
        return $data;
    }

    /**
     * 获取父级ID
     * @param $pid  父ID
     * @return mixed
     */
    public static function findFatherId($pid){
        return self::where('id',$pid)->value('pid');
    }

    /**
     * @param $method
     */
    public function setHttpMethodAttribute($method)
    {
        if (is_array($method)) {
            $this->attributes['http_method'] = implode(',', $method);
        }else{
            $this->attributes['http_method'] = $method;
        }
    }

    /**
     * @param $method
     *
     * @return array
     */
    public function getHttpMethodAttribute($method)
    {
        if (is_string($method)) {
            return array_filter(explode(',', $method));
        }

        return $method;
    }

    /**
     * 获取默认权限ID
     */
    public static function getNormal()
    {
        $normal_id = self::where('name','默认权限')->value('id');
        return self::where('pid',$normal_id)->pluck('id')->toArray();
    }

    /**
     * 获取当前用户权限菜单.
     *
     * @return void
     */
    public static function menus()
    {
        // 当前登录的用户id
        $user_id = Auth::user('admin')->id;
        // 查询权限内的菜单
        $lists = self::join('admin_role_permission as role_permission', 'admin_permission.id', '=', 'role_permission.permission_id')
            ->join('admin_role','role_permission.role_id', '=', 'admin_role.id')
            ->join('admin_user_role as user_role', 'admin_role.id', '=', 'user_role.role_id')
            ->where('user_role.user_id', '=', $user_id)
            ->where('admin_permission.menu_switch', '=', 2)
            ->distinct('admin_permission.id')
            ->orderBy('admin_permission.pid', 'desc')
            ->select('admin_permission.pid', 'admin_permission.id',
                'admin_permission.name', 'admin_permission.icon',
                'admin_permission.http_path as url', 'admin_permission.sort'
                , 'admin_permission.slug'
            )
            ->get()
            ->toArray();

        // 查询权限内的路由
        $menus = self::join('admin_role_permission as role_permission', 'admin_permission.id', '=', 'role_permission.permission_id')
            ->join('admin_role','role_permission.role_id', '=', 'admin_role.id')
            ->join('admin_user_role as user_role', 'admin_role.id','=','user_role.role_id')
            ->where('user_role.user_id', '=', $user_id)
            ->where('admin_permission.http_path','!=','javascript')
            ->distinct('admin_permission.id')
            ->orderBy('admin_permission.pid','desc')
            ->select('admin_permission.http_path as url')
            ->get()
            ->toArray();
        $routes = array_column($menus, 'url');

        // 让id 键值反转 组成一维数组
        $pid_map_id = array_flip(array_column($lists,'id'));
        $data = [];
        foreach ($lists as $k=>$list){
            if($list['pid'] == 0){
                array_push($data,$lists[$k]);
            }else{
                if(!key_exists('childs',$lists[$pid_map_id[$list['pid']]])){
                    $lists[$pid_map_id[$list['pid']]]['childs']=[];
                }
                $lists[$pid_map_id[$list['pid']]]['childs'][] = $lists[$k];
            }
        }
        // 重新排序
        array_multisort(array_column($data,'sort'),SORT_ASC,$data);
        foreach ($data as $k=>$v) {
            if (isset($v['childs'])) {
                array_multisort(array_column($data[$k]['childs'],'sort'),SORT_ASC,$data[$k]['childs']);
            }
        }
        return ['data'=>$data, 'routes'=>$routes];
    }

    /**
     * 获取当前用户菜单
     *
     * @return mixed
     */
    public static function getLeftMenu(){
        // 当前登录的用户id
        $user_id = Auth::user('admin')->id;
        // 查询权限内的菜单
        $lists = self::join('admin_role_permission as role_permission', 'admin_permission.id', '=', 'role_permission.permission_id')
            ->join('admin_role','role_permission.role_id', '=', 'admin_role.id')
            ->join('admin_user_role as user_role', 'admin_role.id', '=', 'user_role.role_id')
            ->where('user_role.user_id', '=', $user_id)
            ->where('admin_permission.menu_switch', '=', 2)
            ->distinct('admin_permission.id')
            ->orderBy('admin_permission.pid', 'desc')
            ->select('admin_permission.pid', 'admin_permission.id',
                'admin_permission.name', 'admin_permission.icon',
                'admin_permission.http_path as url', 'admin_permission.url as route','admin_permission.sort'
                , 'admin_permission.slug'
            )
            ->get()
            ->toArray();
        // 让id 键值反转 组成一维数组
        $pid_map_id = array_flip(array_column($lists,'id'));
        $data = [];
        foreach ($lists as $k=>$list){
            if($list['pid'] == 0){
                array_push($data,$lists[$k]);
            }else{
                if(!key_exists('childs',$lists[$pid_map_id[$list['pid']]])){
                    $lists[$pid_map_id[$list['pid']]]['childs']=[];
                }
                $lists[$pid_map_id[$list['pid']]]['childs'][] = $lists[$k];
            }
        }
        // 重新排序
        array_multisort(array_column($data,'sort'),SORT_ASC,$data);
        foreach ($data as $k=>$v) {
            if (isset($v['childs'])) {
                array_multisort(array_column($data[$k]['childs'],'sort'),SORT_ASC,$data[$k]['childs']);
            }
        }
        return $data;
    }

    /**
     * 获取当前用户权限
     * sql 运行时间 0.048s
     * @return mixed
     */
    public static function gePermission(){
        // 当前登录的用户id
        $user_id = Auth::user('admin')->id;
        // 查询权限内的路由
        $menus = self::join('admin_role_permission as role_permission', 'admin_permission.id', '=', 'role_permission.permission_id')
            ->join('admin_role','role_permission.role_id', '=', 'admin_role.id')
            ->join('admin_user_role as user_role', 'admin_role.id','=','user_role.role_id')
            ->where('user_role.user_id', '=', $user_id)
            ->where('admin_permission.http_path','!=','javascript')
            ->distinct('admin_permission.id')
            ->orderBy('admin_permission.pid','desc')
            ->select('admin_permission.http_path as url')
            ->get()
            ->toArray();
        $routes = array_column($menus, 'url');
        return $routes;
    }

    /**
     * 获取分配权限所需要的菜单
     * @param $menu_ids array 当前用户的权限
     * @return array
     */
    public static function getRoleMenus($menu_ids)
    {
        // 查询所有的权限
        $list = self::select('id', 'pid', 'name as title')
            ->orderBy('level', 'DESC')
            ->orderBy('id')
            ->get()
            ->toArray();
        $area_id_2_index = array_flip(array_column($list, 'id'));

        $temp = [];

        foreach ($list as &$area) {
            if ($area['pid'] == 0) {
                //$area['selected'] = true;
                $area['expand'] = in_array($area['id'],$menu_ids) ? true: false;
                array_push($temp, $area);
                continue;
            }else{
                $area['checked'] = in_array($area['id'],$menu_ids) ? true : false;
            }

            $parent_index = $area_id_2_index[$area['pid']]; //父级所在数组索引
            if (!array_key_exists('children', $list[$parent_index])) {
                $list[$parent_index]['children'] = [];
            }
            array_push($list[$parent_index]['children'], $area);
        }
        return $temp;
    }

    /**
     * 获取列表(分页)
     * @param $where 查询条件
     * @param $orderBy 排序
     * @param int $page 页码
     * @param $limit 每页显示条数
     * @return array
     */
    public static function getData($where,$orderBy,$page=1,$limit){
        $limit = isset($limit) ? $limit : config('exam.pageSize');
        $result = self::where($where);
        if ($orderBy) {
            foreach ($orderBy as $key=>$val) {
                $result->orderBy($val[0], $val[1]);
            }
        }else{
            $result->orderBy('sort','asc');
        }
        $total = $result->count();

        $data = $result->skip(($page-1)*$limit)->take($limit)->get()->toArray();

        return ['total'=>$total,'data'=>$data];
    }

    /**
     * 获取列表(不分页)
     * @param $where 查询条件
     * @param $orderBy 排序
     * @return array
     */
    public static function allData($where,$orderBy){
        $result = self::where($where);
        if ($orderBy) {
            foreach ($orderBy as $key=>$val) {
                $result->orderBy($val[0], $val[1]);
            }
        }else{
            $result->orderBy('id');
        }
        $data = $result->get()->toArray();
        return $data;
    }

    /**
     * 全部数据
     * @param int $pid
     * @return array
     */
    public static function dataGroup1($pid=0){
        $list = self::where('pid', $pid)->get();
        $newArr = array();
        if ($list->first()) {
            foreach ($list as $item) {
                if ($item['pid'] == $pid) {
                    $item['children'] = self::dataGroup($item['id']);
                    $newArr[] = $item;
                }
            }
        }
        return $newArr;
    }

    /**
     * 获取所有数据
     */
    public static function dataGroup(){
        $data = self::select(['id as value', 'pid', 'name as label', 'level'])
            ->orderBy('level', 'DESC')
            ->orderBy('id')
            ->get()
            ->map(function ($append) {
                return $append->setAppends([]);
            })
            ->toArray();
        $area_id_2_index = array_flip(array_column($data, 'value'));

        $temp = [];

        foreach ($data as &$area) {
            if ($area['pid'] == 0){
                array_push($temp, $area);
                continue;
            }

            $parent_index= $area_id_2_index[$area['pid']]; //父级所在数组索引
            if(!array_key_exists('children', $data[$parent_index])){
                $data[$parent_index]['children'] = [];
            }

            array_push($data[$parent_index]['children'], $area);
        }
        return $temp;
    }

    /**
     * 获取所有数据
     */
    public static function dataSaveFile(){
        $data = self::select(['id', 'pid', 'name', 'level','http_path','menu_switch','http_method','url'])
            ->orderBy('level', 'DESC')
            ->orderBy('id')
            ->get()
            ->toArray();
        $area_id_2_index = array_flip(array_column($data, 'id'));

        $temp = [];

        foreach ($data as &$area) {
            if ($area['pid'] == 0){
                array_push($temp, $area);
                continue;
            }

            $parent_index= $area_id_2_index[$area['pid']]; //父级所在数组索引
            if(!array_key_exists('children', $data[$parent_index])){
                $data[$parent_index]['children'] = [];
            }

            array_push($data[$parent_index]['children'], $area);
        }
        //如果不存目录则创建
        if(!file_exists(public_path().'/menu')){
            mkdir(public_path().'/menu');
//            chmod('./area_json', '0777');
        }

        //独占锁更新文件
        file_put_contents(public_path().'/menu/all.json', json_encode($temp));

        //独占锁更新 json 更新日期
        file_put_contents(public_path().'/menu/all.lock', json_encode(['time'=>time()]));
        unset($data);
        unset($temp);
        return true;
    }

    /**
     * 查询IDs中是否为父级
     * @param $ids
     * @return boolean
     */
    public static function isFather($ids){
        foreach ($ids as $item) {
            if (self::childrenNum($item) > 0) {
                return true;
                break;
            }
        }
        return false;
    }

    /**
     * 下级数量
     * @param $id 菜单ID
     * @return boolean
     */
    public static function childrenNum($id){
        return self::where('pid',$id)->count();
    }

    /**
     * 编辑
     * @param array $where 条件
     * @param array $field 字段
     * @return mixed
     */
    public static function modify($where=array(),$field=array()){
        return self::where($where)->update($field);
    }


    /**
     * 获取分配权限所需要的菜单
     * @param $pid int 父级ID默认0
     * @param $menu_ids array 所属权限菜单ID
     * @param $role_id int 所需分配权限角色ID
     * @return array
     */
    public static function getRoleMenu($pid = 0, $menu_ids, $role_id = 0)
    {
        $where['pid'] = $pid;
        $where['menu_switch'] = 2; // 显示的菜单
        $list = self::select('id', 'pid', 'name')
            ->where($where)
            ->orderBy('sort')
            ->get()
            ->toArray();
        $data = [];
        foreach ($list as $index => $item) {
            $map['id'] = $item['id'];
            $map['title'] = $item['name'];
//            $map['selected'] = true;
            if ($role_id) {
                $tmp = self::where('pid', $item['pid'])->pluck('id')->toArray();
                if ($tmp) {
                    foreach ($tmp as $i => $v) {
                        $tmp2 = AdminRolePermission::where([['role_id', $role_id], ['permission_id', $v]])->count();
                        if (!$tmp2) {
                            $map['checked'] = false;
                            break;
                        }else{
                            $map['checked'] = true;
                        }

                    }
                } else {
                    $map['checked'] = AdminRolePermission::where([['role_id', $role_id], ['permission_id', $item['id']]])->count() ? true : false;
                }
                $map['expand'] = AdminRolePermission::where([['role_id', $role_id], ['permission_id', $item['id']]])->count() ? true : false;

            } else {
                $map['checked'] = false;
                $map['expand'] = false;
            }
            $map['children'] = self::getRoleMenu($item['id'], $menu_ids, $role_id);
            if (empty($menu_ids) || !in_array($item['id'], $menu_ids)) {
                unset($map);
            } else {
                if (!$map['children']) {
                    unset($map['children']);
                }
                $data[] = $map;
            }
        }
        return $data;
    }

    /**
     * 查看数组的权限父级ID是否存在
     * @param array $permission
     * @return mixed
     */
    public static function getParentIds($permission){
        // 查询数组的所有父级ID
        $parentIds = self::whereIn('id',$permission)->pluck('pid')->toArray();
        $new_arr = array_merge($permission,$parentIds);
        return array_unique($new_arr);
    }
}